package com.wondertek.common.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson2.JSONObject;
import com.wondertek.common.base.Result;
import com.wondertek.common.constant.SysConstant;
import com.wondertek.common.util.base.PathMatcherUtil;
import com.wondertek.common.util.base.ServletUtil;
import com.wondertek.common.util.security.LoginUser;
import com.wondertek.common.util.security.SecurityUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

/**
 * @author: gongjiangtao
 * @date: 2024/7/22 09:55
 * @Description: 认证filter
 * @Version: 1.0
 */
@WebFilter(filterName = "appAuthFilter", urlPatterns = {"/app/*"})
@Order(1)
@Slf4j
public class AppAuthFilter extends OncePerRequestFilter {

    private static final String LOGIN_TOKEN_KEY = "iot:dh:app:login:token:";

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 无需登录的接口
     */
    @Resource
    private IgnoreUrlsConfig config;

    @Override
    protected void initFilterBean() throws ServletException {
        log.info("appAuthFilter被创建,对app接口鉴权");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        // 处理跨域问题
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "false");
        // 预检请求
        if(request.getMethod().equals(HttpMethod.OPTIONS.name())){
            response.setStatus(HttpServletResponse.SC_OK);
            return ;
        }

        int contextPathLength = request.getContextPath().length();
        String uri = request.getRequestURI();
        uri = uri.substring(contextPathLength);


        String acceptLanguage = request.getHeader(SysConstant.ACCEPTLANGUAGE);
        Locale locale = Locale.CHINA;
        if(StrUtil.isNotBlank(acceptLanguage)) {
            String[] splitLanguage = acceptLanguage.split("_");
            if (splitLanguage.length > 1) {
                locale = Locale.of(splitLanguage[0], splitLanguage[1]);
            }
        }
        LocaleContextHolder.setLocale(locale);

        // 过滤掉无需登陆的接口
        if(!PathMatcherUtil.matches(config.getPermitUrls(),uri)){
            // 判断是否有请求头
            String authorization = request.getHeader(SysConstant.AUTHORIZATION);
            if(StrUtil.isBlank(authorization)){
                ServletUtil.out(response, JSONObject.toJSONString(Result.error(HttpStatus.HTTP_UNAUTHORIZED,"unauthorize.error")));
                return;
            }
            String[] authArray = authorization.trim().split(" ");
            if(authArray.length != 2){
                ServletUtil.out(response, JSONObject.toJSONString(Result.error(HttpStatus.HTTP_UNAUTHORIZED,"unauthorize.error")));
                return;
            }
            String tokenMark = authArray[0];
            String token = authArray[1];
            if(!StrUtil.equals(SysConstant.BEARER,tokenMark)){
                ServletUtil.out(response, JSONObject.toJSONString(Result.error(HttpStatus.HTTP_UNAUTHORIZED,"unauthorize.error")));
                return;
            }

            // 判断token是否过期
            LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(LOGIN_TOKEN_KEY + token);
            if(null == loginUser){
                ServletUtil.out(response, JSONObject.toJSONString(Result.error(HttpStatus.HTTP_UNAUTHORIZED,"unauthorize.not.allowed.login.again")));
                return;
            }

            // 判断是否是安装员
            if(StrUtil.equals("1", loginUser.getType())){
                // todo 路径进行判断
                List<String> pathList = Lists.newArrayList();
                pathList.add("/app/sys/auth/**");
                pathList.add("/app/business/installer/**");
                if(!PathMatcherUtil.matches(pathList,uri)){
                    ServletUtil.out(response, JSONObject.toJSONString(Result.error(HttpStatus.HTTP_FORBIDDEN,"authority.error")));
                    return;
                }
            }

            SecurityUtil.SecurityContext.setLoginUser(loginUser);
        }
        try {
            filterChain.doFilter(request, response);
        }finally {
            SecurityUtil.SecurityContext.remove();
            LocaleContextHolder.resetLocaleContext();
        }
    }
}
